//挖矿相关数据结构及获取接口
package model

import (
	"database/sql"
	"errors"
	"github.com/jmoiron/sqlx"
	"zimuzu_cvn_web_api/config"
	"zimuzu_cvn_web_api/pkg/e"
)

const (
	NodeTypeRouter = 3
	NodeTypeLinux  = 2
	NodeTypePc     = 1
	NodeTypeALL    = 0
)

type MinerRoleResponse struct {
	Role        int   `json:"role"`
	SuperNodeId int64 `json:"super_node_id"`
}

type NodeTotalData struct {
	LastCvn       string  `json:"lastCvn"`       //昨日收益
	TotalCvn      string  `json:"totalCvn"`      //累计收益
	LastFlow      string  `json:"lastFlow"`      //昨日贡献量
	UserTotalFlow string  `json:"userTotalFlow"` //累计贡献量
	TotalFlow     string  `json:"totalFlow"`     //昨日全网贡献量
	LastAllCvn    string  `json:"lastAllCvn"`    //昨日全网CDN收入
	Rate          string  `json:"rate"`          //用户占全网比例
	UserWithCvn   float64 `json:"userWithCvn"`   //用户可用余额
	UserUnWithCvn float64 `json:"userUnWithCvn"` //用户不可用余额
	PledgeNums    int64   `json:"pledgeNums"`    //质押节点数
	UnPledgeNums  int64   `json:"unPledgeNums"`  //非质押节点数
	MiningCount   int64   `json:"miningCount"`   //开启挖矿的节点数
	NodeCount     int64   `json:"nodeCount"`     //节点总数
	SuperName     string  `json:"superName"`     //超级节点名称
}

// 根据主键ID查询详情信息
type ListIdParams struct {
	ListId int64 `form:"list_id"`
}

// 单节点质押&解除
type NodePledgeParams struct {
	Way    int   `form:"way"`
	NodeId int64 `form:"node_id"`
}

// 批量节点质押&解除
type NodePledgeBatchParams struct {
	Way    int     `form:"way" json:"way"`
	NodeId []int64 `form:"node_id" json:"node_id"`
}

//获取用户路由器台数
//Auth: hupfei
func GetRouterCountById(db sqlx.Queryer, uid int64) (int, error) {
	var count sql.NullInt64
	err := sqlx.Get(db, &count, "SELECT count(*) FROM mg_node where uid = ? and type = ?", uid, NodeTypeRouter)
	if err != nil {
		e.Log("err", "获取路由器数量失败")
	}
	return e.Int64ToInt(count.Int64), err
}

//获取全网linux节点数
//Auth: Xu
func GetLinuxNodeCount(db sqlx.Queryer) (int, error) {
	var count int
	err := sqlx.Get(db, &count, `select count(*) node_count from mg_node where status = 1 and type = ?`, NodeTypeLinux)
	if err != nil {
		e.Log("err", "获取奖励池节点数失败")
	}
	return count, err
}

//获取用户节点数
//source 1 全部的节点数  2 已开启挖矿的节点数
func GetNodeCountByUid(uid int64, source int, nodeType int) (count int64, err error) {
	var c sql.NullInt64
	if source == 1 {
		err = sqlx.Get(config.C.DB.DB, &c, `select count(*) from mg_node where uid = ? and (status = 0 or status = 1) and type = ?`, uid, nodeType)
	} else {
		err = sqlx.Get(config.C.DB.DB, &c, `select count(*) node_count from mg_node where status = 1 and uid = ? and type = ?`, uid, nodeType)
	}
	if err != nil {
		logInfo := "获取节点数失败"
		e.Log("err", uid, logInfo, err)

		err = errors.New(logInfo)
	}
	count = c.Int64
	return
}

//获取全网linux上传量
//Auth: Xu
func GetLinuxFlowSum(db sqlx.Queryer) (int64, error) {
	var sum sql.NullInt64
	err := sqlx.Get(db, &sum, `select sum(up) flow_sum from mg_node_flow where type = ?`, NodeTypeLinux)
	if err != nil {
		e.Log("err", "获取全网linux上传量", err.Error())
	}
	return sum.Int64, err
}

type UserLinuxFlow struct {
	FlowSum    sql.NullInt64 `db:"flow_sum" json:"flow_sum"`
	UpdateTime sql.NullInt64 `db:"update_time" json:"update_time"`
}

//获取单个用户linux上传量
//Auth: Xu
func GetLinuxFlowSumByUid(db sqlx.Queryer, uid int64) (UserLinuxFlow, error) {
	var userLinuxFlow UserLinuxFlow
	err := sqlx.Get(db, &userLinuxFlow, `select sum(f.up)*1024 flow_sum, max(f.time) update_time from mg_node n LEFT JOIN mg_node_flow f ON f.node_id = n.node_id and f.type = ? where n.uid = ? and n.type = ? `, NodeTypeLinux, uid, NodeTypeLinux)
	if err != nil {
		e.Log("err", "获取单个用户linux上传量失败", err.Error())
	}
	return userLinuxFlow, err
}

//获取单个用户通过linux挖矿获得的CVNT数量
//Auth: Xu
func GetLinuxCvntByUid(db sqlx.Queryer, uid int64) (float64, error) {
	var sum sql.NullFloat64
	err := sqlx.Get(db, &sum, `select sum(cvn) cvnt from mg_node_payment where uid = ? and status = 1 and type = ?`, uid, NodeTypeLinux)
	if err != nil {
		e.Log("err", "获取用户CVNT数据失败")
	}
	return sum.Float64, err
}

type UserRouterMiningInfo struct {
	ExchangeSize int64   `db:"exchange_size" json:"exchange_size"`
	Cvn          float64 `db:"cvn" json:"cvn"`
	Counts       int64   `json:"counts"`       //路由器台数
	MiningCounts int64   `json:"miningCounts"` //正在挖矿路由器台数
	PledgeCvnt   float64 `json:"pledgeCvnt"`
}

//获取linux挖矿用户今天截止到当前上传的流量
//Auth: Xu
func GetLinuxTodayUploadByUid(db sqlx.Queryer, uid int64) (int64, error) {
	var sum sql.NullInt64
	zeroUnix := e.GetTodayZeroUnix()
	err := sqlx.Get(db, &sum, `select sum(f.up)*1024 flow_sum from mg_node n LEFT JOIN mg_node_flow f ON f.node_id = n.node_id and n.type = ?  where n.uid = ? and f.time >= ? and f.type = ?`, NodeTypeLinux, uid, zeroUnix, NodeTypeLinux)
	if err != nil {
		e.Log("err", "获取用户累计挖矿数据失败", err.Error())
	}
	return sum.Int64, err
}

// 节点质押&解除
// tokenStatus状态：2-质押 3-解除质押
// TODO 需要扣除 CVN操作，暂时没有处理
// Auth: hzp
func PledgeWithSingleNode(uid, nodeId int64, tokenStatus int) (err error) {
	e.Log("info", "质押节点：uid=", uid, "&nodeId=", nodeId, "&tokenStatus=", tokenStatus)
	// 开启事务
	conn, err := config.C.DB.DB.Begin()
	if err != nil {
		e.Log("err", "质押节点开启事务失败", err.Error())
		return errors.New("质押节点失败，请稍后重试")
	}

	var rowId2, rowId3 int64
	// 更新mg_node
	r2, err2 := conn.Exec("UPDATE mg_node SET token_status = ?, pledge_time = UNIX_TIMESTAMP(now()) "+
		" WHERE node_id = ? AND uid = ? AND status != 2", tokenStatus, nodeId, uid)
	if err2 == nil {
		rowId2, err2 = r2.RowsAffected()
		if err2 != nil {
			e.Log("err", "SinglePledge 更新mg_node表失败(RowsAffected)，nodeId = ", nodeId, err2.Error())
			rowId2 = 0
		}
	} else {
		e.Log("err", "SinglePledge 更新mg_node表失败，nodeId = ", nodeId, err2.Error())
	}

	// 增加计划任务
	r3, err3 := conn.Exec("INSERT INTO mg_token_status_task (node_id, start_time, end_time, status) "+
		"VALUE (?, NOW(), UNIX_TIMESTAMP(DATE_SUB(NOW(),INTERVAL -7 DAY)), 0)", nodeId)
	if err3 == nil {
		rowId3, err3 = r3.RowsAffected()
		if err3 != nil {
			e.Log("err", "SinglePledge 计划任务添加失败(RowsAffected)，nodeId = ", nodeId, err3.Error())
			rowId3 = 0
		}
	} else {
		e.Log("err", "SinglePledge 计划任务添加失败，nodeId = ", nodeId, err3.Error())
	}

	// 提交事务
	if rowId2 > 0 && rowId3 > 0 {
		err = conn.Commit()
		if err != nil {
			e.Log("err", "SinglePledge 事务提交失败", err.Error())
			err = conn.Rollback()
			if err != nil {
				e.Log("err", "SinglePledge 事务回滚失败", err.Error())
			}
			return errors.New("质押失败，请稍后重试")
		}
		e.Log("info", "质押令牌成功：uid-", uid, " nodeId-", nodeId, " tokenStatus-", tokenStatus)
		return nil
	} else {
		e.Log("err", "质押失败 rowId2:", rowId2, ":rowId3:", rowId3)
		err = conn.Rollback()
		if err != nil {
			e.Log("err", "SinglePledge 事务回滚失败", err.Error())
		}
		return errors.New("质押失败")
	}
}

type DateValueStruct struct {
	Date   string  `json:"date" form:"date"`
	Value  float64 `json:"value" form:"value"`
	Value2 float64 `json:"value2" form:"value2"`
}

type GlobalGbpsStruct struct {
	Gbps  float64 `json:"gbps" form:"gbps"`
	Speed string  `json:"speed" form:"speed"`
}

type GlobalList struct {
	Date      string  `json:"date" form:"date"`
	Pledge    float64 `json:"pledge" form:"pledge"`
	UnPledge  float64 `json:"unPledge" form:"unPledge"`
	Online    int     `json:"online" form:"online"`
	New       int     `json:"new" form:"new"`
	MiningCvn float64 `json:"miningCvn" form:"miningCvn"`
	Storage   float64 `json:"storage" form:"storage"`
}

type CdnProfitStruct struct {
	Month   string  `json:"month" form:"month"`
	Profit1 float64 `json:"profit1" form:"profit1"`
	Profit2 float64 `json:"profit2" form:"profit2"`
}
